package tmt.usercenter.web.controller.app;

import com.tmt.annotation.parser.EnumAnnotationParser;
import com.tmt.datatable.editor.impl.DefaultFileDataHolder;
import com.tmt.fileservice.FileSaveMode;
import com.tmt.fileservice.IFileService;
import com.tmt.spring.validation.RegisterValidateHelper;
import org.dozer.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RestController;
import tmt.usercenter.web.bean.TmtSemaphore;
import tmt.usercenter.web.controller.app.bean.*;
import tmt.usercenter.web.domain.RealNameMaterial;
import tmt.usercenter.web.domain.SmHistory;
import tmt.usercenter.web.domain.TmtUser;
import tmt.usercenter.web.domain.enums.AuditStatus;
import tmt.usercenter.web.domain.enums.FuncPointType;
import tmt.usercenter.web.domain.enums.SystemParamCode;
import tmt.usercenter.web.domain.security.UserDetailsImpl;
import tmt.usercenter.web.domain.vo.AppUserInfo;
import tmt.usercenter.web.plugin.filesevice.FileDataResolver;
import tmt.usercenter.web.service.*;
import tmt.usercenter.web.vo.HttpResult;

import java.util.ArrayList;
import java.util.List;

/**
 * 对应APP手机端软件的REST风格的接口
 */
@RestController
public class AppBaseController {

    @Autowired
    protected ClientSystemService clientSystemService;

    @Autowired
    protected SmHistoryService smHistoryService;

    @Autowired
    protected Mapper mapper;

    @Autowired
    protected IFileService fileService;

    @Autowired
    protected TmtUserService userService;

    @Autowired
    protected RealNameMaterialService realNameMaterialService;

    @Autowired
    protected SystemParamService paramService;

    @Autowired
    protected UserInfoConfigService uiConfigService;

    @Autowired
    protected SemaphoreService semaphoreService;

    protected HttpResult<RealNameAuthInfo> applyRealNameAuth(RealNameAuthRequest authRequest,
                                                             UserDetailsImpl userDetails) {

        if (StringUtils.isEmpty(authRequest.getName()))
            return HttpResult.failure("真实姓名不能为空");

        if (!RegisterValidateHelper.validateRealName(authRequest.getName())) {
            return HttpResult.failure("真实姓名必须包含汉字");
        }

        if (StringUtils.isEmpty(authRequest.getCardNo()))
            return HttpResult.failure("证件号码不能为空");

        if (authRequest.getCardType() == null)
            return HttpResult.failure("证件类型不能为空");

        switch (authRequest.getCardType()) {
            case ID_CARD_2:
                if (RegisterValidateHelper.validateIdCard2(authRequest.getCardNo()) != 0)
                    return HttpResult.failure("无效的第二代身份证");
                break;
            case ID_CARD_HK:
                if (RegisterValidateHelper.validateIdCard_HK(authRequest.getCardNo()) != 0)
                    return HttpResult.failure("无效的澳门身份证");
                break;
            case ID_CARD_AM:
                if (!RegisterValidateHelper.validateIdCard_AM(authRequest.getCardNo()))
                    return HttpResult.failure("无效的澳门身份证");
                break;
            case ID_CARD_TW:
                if (!RegisterValidateHelper.validateIdCard_TW(authRequest.getCardNo()))
                    return HttpResult.failure("无效的台湾身份证");
                break;
        }

        Long userId = null;
        String userMobile = null;
        try {
            userId = userDetails.getUserId();
            if (userId == null)
                throw new Exception();

            userMobile = userService.getMobileByUserId(userId);
        } catch (Exception ignored) {
            return HttpResult.failure("当前帐号未登录授权");
        }

        //先检查手机验证码是否有效。
        SmHistory history = smHistoryService.findLastValidByToMobileAndFuncPoint(userMobile, FuncPointType.REAL_NAME_AUTH);
        if (history == null || !history.getContent().contains(authRequest.getCheckCode()))
            return HttpResult.failure("手机号码或验证码无效");

        if (!clientSystemService.existsByClientId(authRequest.getClientId()))
            return HttpResult.failure("客户端ID无效");

        if (authRequest.getFrontFile() != null && !authRequest.getFrontFile().isEmpty()) {
            try {
                DefaultFileDataHolder holder = new DefaultFileDataHolder("front", authRequest.getFrontFile());
                String filePath = fileService.getFileDispatcher().getNewFilePath(RealNameMaterial.class, 0, "front",
                        holder.getFileName(), FileSaveMode.TEMPARARY);
                fileService.save(filePath, new FileDataResolver(holder));
                authRequest.setFront(holder.getFileName());
            } catch (Exception ex) {
                return HttpResult.failure("证件正面照片保存失败");
            }
        } else {
            return HttpResult.failure("缺少证件正面照片");
        }

        if (authRequest.getBackFile() != null && !authRequest.getBackFile().isEmpty()) {
            try {
                DefaultFileDataHolder holder = new DefaultFileDataHolder("back", authRequest.getBackFile());
                String filePath = fileService.getFileDispatcher().getNewFilePath(RealNameMaterial.class, 0, "back",
                        holder.getFileName(), FileSaveMode.TEMPARARY);
                fileService.save(filePath, new FileDataResolver(holder));
                authRequest.setBack(holder.getFileName());
            } catch (Exception ex) {
                return HttpResult.failure("证件背面照片保存失败");
            }
        } else {
            return HttpResult.failure("缺少证件背面照片");
        }

        try {
            RealNameMaterial material = new RealNameMaterial();
            mapper.map(authRequest, material);

            material.setUser(new TmtUser(userId));
            material.setAuditStatus(AuditStatus.AUDITING);
            material = realNameMaterialService.create(material);

            //作废当前的验证码
            smHistoryService.updateValid(history.getId(), false);

            RealNameAuthInfo realNameAuthInfo = new RealNameAuthInfo();
            mapper.map(material, realNameAuthInfo);

            return HttpResult.success("操作成功", realNameAuthInfo);
        } catch (Exception ex) {
        }

        return HttpResult.failure("实名认证申请提交失败");
    }

    protected HttpResult<RealNameAuthInfo> deleteRealNameAuthById(Long rlId, UserDetailsImpl userDetails) {
        Long userId = null;
        try {
            userId = userDetails.getUserId();
        } catch (Exception ignored) {
        }

        if (userId == null) {
            return HttpResult.failure("当前用户未登录授权");
        }

        RealNameMaterial material = realNameMaterialService.loadEntity(RealNameMaterial.class, rlId, "1");
        if (material == null) {
            return HttpResult.failure("要删除的目标记录不存在");
        }

        if (!userId.equals(material.getUser().getId())) {
            return HttpResult.failure("无权删除其他人的实名认证记录");
        }

        TmtSemaphore semaphore = semaphoreService.getSemaphore(RealNameMaterial.class, material.getId());
        semaphore.acquire();
        try {
            //在信号量中重新加载目标对象。
            material = realNameMaterialService.findById(rlId);
            if (material.getAuditStatus() != AuditStatus.AUDIT_SUCCESS) {
                realNameMaterialService.delete(material);
            }
        } catch (Exception ex) {
            return HttpResult.failure("删除实名认证记录异常");
        } finally {
            semaphore.release();
        }

        return queryRealNameAuthResult(userDetails);
    }

    protected HttpResult<RealNameAuthInfo> queryRealNameAuthResult(UserDetailsImpl userDetails) {

        Long userId = null;
        try {
            userId = userDetails.getUserId();
        } catch (Exception ignored) {
        }

        if (userId == null)
            return HttpResult.failure("当前帐号未登录授权");

        RealNameAuthInfo info = new RealNameAuthInfo();
        userService.initialRealNameAuthInfo(userId, info);

        RealNameMaterial material = realNameMaterialService.findFirstByUserIdOrderByIdDesc(userId);
        if (material == null) {
            info.setAuditStatus(AuditStatus.NOT_APPLY);
        } else {
            mapper.map(material, info);
            info.setAuditStatusStr(EnumAnnotationParser.getTitle(info.getAuditStatus()));
        }
        return HttpResult.success("操作成功", info);
    }

    protected HttpResult<String> updateUserMobile(ChangeMobileRequest request, UserDetailsImpl userDetails) {
        Long userId = null;
        try {
            userId = userDetails.getUserId();
        } catch (Exception ignored) {
        }

        if (userId == null)
            return HttpResult.failure("当前帐号未登录授权");

        try {
            String mobile = userService.getMobileByUserId(userId);

            SmHistory history1 = null;
            if (!StringUtils.isEmpty(mobile)) {
                //先检查原手机验证码是否有效。
                history1 = smHistoryService.findLastValidByToMobileAndFuncPoint(mobile, FuncPointType.UPDATE_MOBILE);
                if (history1 == null || !history1.getContent().contains(request.getVerifyCode()))
                    return HttpResult.failure("原手机验证码无效");
            }

            //先检查手机验证码是否有效。
            SmHistory history = smHistoryService.findLastValidByToMobileAndFuncPoint(request.getMobile(), FuncPointType.UPDATE_MOBILE);
            if (history == null || !history.getContent().contains(request.getCheckCode()))
                return HttpResult.failure("手机号码或验证码无效");

            //验证号码的唯一性或最大注册数。
            try {
                uiConfigService.validateMobileRule(request.getMobile(), userId, request.getClientId());
            } catch (Exception ex) {
                return HttpResult.failure(ex.getMessage());
            }

            userService.updateMobile(userId, request.getMobile());

            smHistoryService.updateValid(history.getId(), false);

            if (!StringUtils.isEmpty(mobile)) {
                smHistoryService.updateValid(history1.getId(), false);
            }

            return HttpResult.success("操作成功", request.getMobile());
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return HttpResult.failure("操作失败");
    }

    protected HttpResult<Boolean> updateNickName(ChangeNickNameRequest request, UserDetailsImpl userDetails) {
        Long userId = null;
        try {
            userId = userDetails.getUserId();
        } catch (Exception ignored) {
        }

        if (userId == null)
            return HttpResult.failure("当前帐号未登录授权");

        try {
            userService.updateNickName(userId, request.getNewNickName());
            return HttpResult.success("操作成功", true);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return HttpResult.failure("操作失败");
    }

    protected HttpResult<String> updateAvatar(ChangeAvatarRequest request, UserDetailsImpl userDetails) {
        Long userId = null;
        try {
            userId = userDetails.getUserId();
        } catch (Exception ignored) {
        }

        if (userId == null)
            return HttpResult.failure("当前帐号未登录授权");

        if (request.getNewAvatar() != null && !request.getNewAvatar().isEmpty()) {
            try {
                DefaultFileDataHolder holder = new DefaultFileDataHolder("avatar", request.getNewAvatar());
                String filePath = fileService.getFileDispatcher().getNewFilePath(TmtUser.class, userId, "avatar",
                        holder.getFileName(), FileSaveMode.TEMPARARY);
                //保存头像图片。
                fileService.save(filePath, new FileDataResolver(holder));
                //更新用户头像。
                userService.updateAvatar(userId, holder.getFileName());
                //重新加载用户对象。
                TmtUser user = userService.findById(userId);
                //获取用户头像全路径Url;
                String url = fileService.getFileDispatcher().getFileUrl(user, "avatar", FileSaveMode.PERSIST);
                if (!StringUtils.isEmpty(url))
                    return HttpResult.success("操作成功", url);

            } catch (Exception ex) {
                return HttpResult.failure("用户头像照片保存失败");
            }
        } else {
            return HttpResult.failure("缺少用户头像照片");
        }

        return HttpResult.failure("更新用户头像失败");
    }

    protected HttpResult<AppUserInfo> queryInvitedUserList(InvitedUsersRequest request, UserDetailsImpl userDetails) {

        Long userId = null;
        try {
            userId = userDetails.getUserId();
        } catch (Exception ignored) {
        }

        if (userId == null)
            return HttpResult.failure("当前帐号未登录授权");

        TmtUser user = userService.findById(userId);
        if (user != null) {
            AppUserInfo info = new AppUserInfo();
            mapper.map(user, info);

            int maxLevel = paramService.getSystemParamValue(SystemParamCode.MAX_LEVEL_FOR_FANS_LIST, int.class);
            maxLevel = Math.min(maxLevel, request.getMaxLevel());

            //加载用户的锁粉列表。
            List<String> clientIds = new ArrayList<>();
            clientIds.add(request.getClientId());
            clientIds.add("lingling9.mall");
            findAllInvitedUsers(info, clientIds, maxLevel);

            return HttpResult.success("操作成功", info);
        }

        return HttpResult.success("操作失败");
    }

    private void findAllInvitedUsers(AppUserInfo userInfo, List<String> clientIds, int level) {

        List<AppUserInfo> invitedUserList = new ArrayList<>();
        List<TmtUser> userList = userService.findAllByIntroducerCodeAndOriginSystemClientIdIn(userInfo.getId(), clientIds);
        userInfo.setInvitedCount(userList.size());
        userInfo.setInvitedUsers(invitedUserList);

        int newLevel = level - 1;
        if (newLevel < 0)
            return;

        userList.forEach(x -> {
            AppUserInfo info = new AppUserInfo();
            mapper.map(x, info);
            String url = fileService.getFileDispatcher().getFileUrl(x, "avatar", FileSaveMode.PERSIST);
            info.setAvatar(url);
            findAllInvitedUsers(info, clientIds, newLevel);
            invitedUserList.add(info);
        });
    }

}
